package com.simen.git.commit.code;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * <sample>
 * java -jar GitServerHelper.jar c:\workdirectory\projectDir push "commit log"
 * <p>
 * java -jar GitServerHelper.jar push "commit log"
 * <p>
 * java -jar GitServerHelper.jar pushOnly "commit log"
 * <p>
 * java -jar GitServerHelper.jar clone "https://github.com/someone/project.git"
 * </sample>
 *
 * @author Created by Simen.
 * @date 创建日期 2018/9/20 11:31
 * @modify 修改者 Simen
 */
public class GitServer {

    private static final String DEFAULT_COMMIT_MSG = "auto update by GitServer";

    public static final String GIT_CLONE = "clone";
    public static final String GIT_COMMIT_ALL_WITH_PUSH = "push";
    public static final String GIT_PUSH_ONLY = "pushOnly";

    public static void main(String[] args) {
        try {
            new GitServer(args).start();
        } catch (GitException e) {
            e.printStackTrace();
        }
    }

    private String[] args;

    private String gitOrder;

    private File workDirectory;
    private String commitLog;

    private String cloneUrl;

    public GitServer(String[] args) throws GitException {
        this.args = args;

        this.initGitServer();
    }

    private void initGitServer() throws GitException {
        if (GIT_CLONE.equals(args[0])
                || GIT_COMMIT_ALL_WITH_PUSH.equals(args[0])
                || GIT_PUSH_ONLY.equals(args[0])) {
            gitOrder = args[0];

            //没有指定工作目录时,默认取当前目录为工作目录
            String userDir = System.getProperty("user.dir");

            if (userDir == null) {
                workDirectory = new File("").getAbsoluteFile();
            } else {
                workDirectory = new File(userDir).getAbsoluteFile();
            }

            System.out.println("will use current directory as work directory." + workDirectory.getAbsolutePath());

            if (GIT_CLONE.equals(gitOrder)) {
                if (args.length < 2) {
                    throw new GitException("you should set git url param");
                }
                cloneUrl = args[1];
            } else {
                commitLog = args.length > 1 ? args[1] : DEFAULT_COMMIT_MSG;
            }
        } else {
            //使用用户指定的工作目录
            workDirectory = new File(args[0]).getAbsoluteFile();

            if (args.length < 2) {
                throw new GitException("unknown git order!!!\nthe order should be one of those:\n" +
                        GIT_CLONE + "\n" +
                        GIT_COMMIT_ALL_WITH_PUSH + "\n" +
                        GIT_PUSH_ONLY + "\n");
            }

            gitOrder = args[1];

            if (GIT_CLONE.equals(gitOrder)) {
                if (args.length < 3) {
                    throw new GitException("you should set git url param");
                }
                cloneUrl = args[2];
            } else {
                commitLog = args.length > 2 ? args[2] : DEFAULT_COMMIT_MSG;
            }
        }

        if (!workDirectory.exists() || !workDirectory.isDirectory()) {
            if (!workDirectory.mkdirs()) {
                throw new GitException("create work directory is fail. " + workDirectory.getPath());
            }
        }
    }

    public void start() throws GitException {
        if (GIT_CLONE.equals(gitOrder)) {
            gitClone();
        } else if (GIT_COMMIT_ALL_WITH_PUSH.equals(gitOrder)) {
            push();
        } else if (GIT_PUSH_ONLY.equals(gitOrder)) {
            pushOnly();
        } else {
            throw new GitException("unknown git order!!!\nthe order should be one of those:\n" +
                    GIT_CLONE + "\n" +
                    GIT_COMMIT_ALL_WITH_PUSH + "\n" +
                    GIT_PUSH_ONLY + "\n");
        }
    }

    public void gitClone() throws GitException {
        try {
            printLog(new ProcessBuilder(
                    "git",
                    "clone",
                    cloneUrl
            )
                    .directory(workDirectory)
                    .start());
        } catch (InterruptedException e) {
            throw new GitException(e);
        } catch (IOException e) {
            throw new GitException(e);
        }
    }

    public void push() throws GitException {
        try {
            //添加本地所有改动
            printLog(new ProcessBuilder(
                    "git",
                    "add",
                    "--all"
            )
                    .directory(workDirectory)
                    .start());
        } catch (InterruptedException e) {
            throw new GitException(e);
        } catch (IOException e) {
            throw new GitException(e);
        }

        try {
            //commit到本地仓库
            printLog(new ProcessBuilder(
                    "git",
                    "commit",
                    "-m",
                    commitLog
            )
                    .directory(workDirectory)
                    .start());
        } catch (InterruptedException e) {
            throw new GitException(e);
        } catch (IOException e) {
            throw new GitException(e);
        }

        pushOnly();
    }

    public void pushOnly() throws GitException {
        try {
            //push到远程origin主机
            printLog(new ProcessBuilder(
                    "git",
                    "push",
                    "-u",
                    "origin"
            )
                    .directory(workDirectory)
                    .start());
        } catch (InterruptedException e) {
            throw new GitException(e);
        } catch (IOException e) {
            throw new GitException(e);
        }
    }

    private void printLog(final Process process) throws InterruptedException {
        new Thread() {
            @Override
            public void run() {
                try {
                    printStreamContent(process.getInputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                try {
                    printErrStreamContent(process.getErrorStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        process.waitFor();
    }

    public static void printStreamContent(InputStream is) throws IOException {
        byte[] buf = new byte[1024];
        int read = 0;

        while ((read = is.read(buf)) != -1) {
            System.out.println(new String(buf, 0, read));
        }

    }

    public static void printErrStreamContent(InputStream is) throws IOException {
        byte[] buf = new byte[1024];
        int read = 0;

        while ((read = is.read(buf)) != -1) {
            System.err.println(new String(buf, 0, read));
        }

    }

}
